
package com.dianban.weixin.util;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.dianban.config.redis.RedisUtil;
import org.apache.commons.lang.StringUtils;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.InputSource;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.StringReader;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Map.Entry;


public class WeiXinUtils {

	private static Logger log = LoggerFactory.getLogger(WeiXinUtils.class);

	public static String CreateNoncestr(int length) {
		String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
		String res = "";
		for (int i = 0; i < length; i++) {
			Random rd = new Random();
			res += chars.indexOf(rd.nextInt(chars.length() - 1));
		}
		return res;
	}

	public static String CreateNoncestr() {
		String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
		String res = "";
		for (int i = 0; i < 16; i++) {
			Random rd = new Random();
			res += chars.charAt(rd.nextInt(chars.length() - 1));
		}
		return res;
	}

	public static boolean IsNumeric(String str) {
		if (str.matches("\\d *")) {
			return true;
		} else {
			return false;
		}
	}

	public static String getRequestXml(HashMap<String, Object> parameters) {
		StringBuffer sb = new StringBuffer();
		sb.append("<xml>");
		Set es = parameters.entrySet();
		Iterator it = es.iterator();
		while (it.hasNext()) {
			Map.Entry entry = (Map.Entry) it.next();
			String k = (String) entry.getKey();
			Object v =  entry.getValue();
			if ("attach".equalsIgnoreCase(k) || "body".equalsIgnoreCase(k) || "sign".equalsIgnoreCase(k)) {
				sb.append("<" + k + ">" + "<![CDATA[" + v + "]]></" + k + ">");
			} else {
				sb.append("<" + k + ">" + v + "</" + k + ">");
			}
		}
		sb.append("</xml>");
		return sb.toString();
	}

	public static String ArrayToXml(HashMap<String, Object> arr) {
		String xml = "<xml>";

		Iterator<Entry<String, Object>> iter = arr.entrySet().iterator();
		while (iter.hasNext()) {
			Entry<String, Object> entry = iter.next();
			String key = entry.getKey();
			String val = String.valueOf(entry.getValue());
			if (IsNumeric(val)) {
				xml += "<" + key + ">" + val + "</" + key + ">";

			} else
				xml += "<" + key + "><![CDATA[" + val + "]]></" + key + ">";
		}

		xml += "</xml>";
		return xml;
	}

	public static String toXml(HashMap<String, Object> arr) {
		String xml = "<xml>";
		Iterator<Entry<String, Object>> iter = arr.entrySet().iterator();
		while (iter.hasNext()) {
			Entry<String, Object> entry = iter.next();
			String key = entry.getKey();
			String val = String.valueOf(entry.getValue());
			xml += "<" + key + ">" + val + "</" + key + ">";
		}
		xml += "</xml>";
		return xml;
	}

	public static String FormatBizQueryParaMap(Map<String, Object> paraMap, boolean urlencode) throws Exception {

		String buff = "";
		List<Map.Entry<String, Object>> infoIds = new ArrayList<Map.Entry<String, Object>>(paraMap.entrySet());

		Collections.sort(infoIds, new Comparator<Map.Entry<String, Object>>() {
			public int compare(Map.Entry<String, Object> o1, Map.Entry<String, Object> o2) {
				return (o1.getKey()).toString().compareTo(o2.getKey());
			}
		});
		for (int i = 0; i < infoIds.size(); i++) {
			Map.Entry<String, Object> item = infoIds.get(i);
			String key = item.getKey();
			String val = item.getValue().toString();
			if (null != val && !"".equals(val) && !"sign".equals(key) && !"key".equals(key)) {
				if (urlencode) {
					val = URLEncoder.encode(val, "utf-8");
				}
				buff += key + "=" + val + "&";

			}
		}

		if (buff.isEmpty() == false) {
			buff = buff.substring(0, buff.length() - 1);
		}
		return buff;
	}

	public static String FormatUrlQueryParaMap(Map<String, Object> paraMap, boolean urlencode) throws Exception {

		String buff = "";
		List<Map.Entry<String, Object>> infoIds = new ArrayList<Map.Entry<String, Object>>(paraMap.entrySet());

		Collections.sort(infoIds, new Comparator<Map.Entry<String, Object>>() {
			public int compare(Map.Entry<String, Object> o1, Map.Entry<String, Object> o2) {
				return (o1.getKey()).toString().compareTo(o2.getKey());
			}
		});
		for (int i = 0; i < infoIds.size(); i++) {
			Map.Entry<String, Object> item = infoIds.get(i);
			String key = item.getKey();
			String val = item.getValue().toString();
			if (null != val && !"".equals(val)) {
				if (urlencode) {
					val = URLEncoder.encode(val, "utf-8");
				}
				buff += key + "=" + val + "&";

			}
		}

		if (buff.isEmpty() == false) {
			buff = buff.substring(0, buff.length() - 1);
		}
		return buff;
	}

	public static String getChildrenText(List children) {
		StringBuffer sb = new StringBuffer();
		if (!children.isEmpty()) {
			Iterator it = children.iterator();
			while (it.hasNext()) {
				Element e = (Element) it.next();
				String name = e.getName();
				String value = e.getTextNormalize();
				List list = e.getChildren();
				sb.append("<" + name + ">");
				if (!list.isEmpty()) {
					sb.append(getChildrenText(list));
				}
				sb.append(value);
				sb.append("</" + name + ">");
			}
		}

		return sb.toString();
	}

	public static InputStream String2Inputstream(String str) {
		return new ByteArrayInputStream(str.getBytes());
	}

	public static HashMap<String, Object> doXMLParse(String strxml) throws Exception {
		if (null == strxml || "".equals(strxml)) {
			return null;
		}
		HashMap<String, Object> m = new HashMap<String, Object>();
		StringReader sr = new StringReader(strxml);
		InputSource is = new InputSource(sr);
		Document doc = (new SAXBuilder()).build(is);
		Element root = doc.getRootElement();
		List list = root.getChildren();
		Iterator it = list.iterator();
		while (it.hasNext()) {
			Element e = (Element) it.next();
			String k = e.getName();
			String v = "";
			List children = e.getChildren();
			if (children.isEmpty()) {
				v = e.getTextNormalize();
			} else {
				v = getChildrenText(children);
			}

			m.put(k, v);
		}

		return m;
	}

	public static String getTimeStamp() {
		return String.valueOf(System.currentTimeMillis() / 1000);
	}


	public static final String APP_ID = "wx6cd862ec6a34428c";
	public static final String APP_SECRET = "60e1ce01a25c480fda8627f86637020e";
	public static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token";
	public static final String USER_INFO_URL = "https://api.weixin.qq.com/cgi-bin/user/info";
	// 发送模板消息
	public static final String SEND_MESSAGE = "https://api.weixin.qq.com/cgi-bin/message/template/send";

	/**
	 * 获取access_token
	 * 	https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html
	 * @return
	 */
	public static String getAccessToken() {
		String accessToken = "";
		try {
			String result = HttpUtils.sendGet(ACCESS_TOKEN_URL, "grant_type=client_credential&appid=" + APP_ID + "&secret=" + APP_SECRET);
			JSONObject jsonObject = JSONObject.parseObject(result);
			if (jsonObject != null) {
				accessToken = (String) jsonObject.get("access_token");
			}
			log.info("getAccessToken:" + result);
			log.info("accessToken:" + accessToken);
		}catch (Exception e){
			e.printStackTrace();
		}

		//{"access_token":"ACCESS_TOKEN","expires_in":7200}
		/*String accessToken = (String) RedisUtil.get("access_token");
		if (StringUtils.isEmpty(accessToken)) {
			String result = HttpUtils.sendGet(ACCESS_TOKEN_URL, "grant_type=client_credential&appid=" + APP_ID + "&secret=" + APP_SECRET);
			log.info("getAccessToken:" + result);
			if (StringUtils.isEmpty(result)) {
				return accessToken;
			}
			JSONObject jsonObject = JSONObject.parseObject(result);
			if (jsonObject != null) {
				accessToken = (String) jsonObject.get("access_token");
				RedisUtil.set("access_token", accessToken, 7100);
			}
		}*/
		return accessToken;
	}

	/**
	 * 根据openid获取微信用户信息
	 * 	https://developers.weixin.qq.com/doc/offiaccount/User_Management/Get_users_basic_information_UnionID.html#UinonId
	 * @param openid
	 * @return
	 */
	public static JSONObject getUserInfo(String openid) {
		//{
		//    "subscribe": 1,
		//    "openid": "o6_bmjrPTlm6_2sgVt7hMZOPfL2M",
		//    "nickname": "Band",
		//    "sex": 1,
		//    "language": "zh_CN",
		//    "city": "广州",
		//    "province": "广东",
		//    "country": "中国",
		//    "headimgurl":"http://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0",
		//    "subscribe_time": 1382694957,
		//    "unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL"
		//    "remark": "",
		//    "groupid": 0,
		//    "tagid_list":[128,2],
		//    "subscribe_scene": "ADD_SCENE_QR_CODE",
		//    "qr_scene": 98765,
		//    "qr_scene_str": ""
		//}
		String result = HttpUtils.sendGet(USER_INFO_URL, "access_token=" + getAccessToken() + "&openid=" + openid + "&lang=zh_CN");
		log.info("getUserInfo:" + result);
		if (StringUtils.isEmpty(result)) {
			return null;
		}
		JSONObject jsonObject = JSONObject.parseObject(result);
		return jsonObject;
	}

	public static void sendTemplateMessage(String openId, Map<String,Object> body) {
		if (StringUtils.isBlank(openId) || body == null ) {
			return;
		}
		String resultStr = "";
		try {
			log.info("发送微信模板消息，请求开始。");
			body.put("touser", openId);
			String url = SEND_MESSAGE + "?access_token="+ getAccessToken();
			JSONObject jsonObject = HttpUtils.httpRequest(url, "POST", JSONObject.toJSONString(body));

		} catch (Exception e) {
			log.error("发送微信模板消息失败：",e.getMessage());
			throw new RuntimeException();
		}
	}

	public static Map<String,Object> genTemplateMessageParam(String url, String wxTemplateId, String... param) {
		Map<String,Object> result = new HashMap();
		Map<String,Object> paramStr =  new HashMap();
		Map<String,Object> item =  null;
		if(StringUtils.isNotBlank(url)){
			result.put("url", url);
		}
		result.put("template_id", wxTemplateId);
		for (int i = 0; i < param.length; i++) {
            item =  new HashMap();
            item.put("color", "#173177");
			if(i == 0){
				item.put("value", param[i]);
				paramStr.put("first", item);
			}else if(i == param.length - 1){
				item.put("value", param[i]);
				paramStr.put("remark", item);
			}else{
				item.put("value", param[i]);
				paramStr.put("keyword"+i, item);
			}
		}
		result.put("data", paramStr);
		return result;
	}

}
